package com.ruoyi.web.api;

import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.service.ISysMenuService;
import org.openapi.common.ApiResult;
import org.openapi.domain.ApiField;
import org.openapi.domain.ApiModel;
import org.openapi.service.IApiLoaderService;
import org.openapi.service.IDbService;
import org.openapi.service.IOpenApiService;
import org.openapi.utils.StrUtil;
import org.openapi.vo.SqlPager;
import org.openapi.vo.TableData;
import org.openapi.vo.TableQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * 低代码入口控制器
 *
 * @author yepanpan
 * @date 2023-10-10
 */
@RestController
@RequestMapping("/dev")
public class DevController {
    @Autowired
    private IDbService dbService;
    @Autowired
    private IApiLoaderService apiLoaderService;
    @Autowired
    private IOpenApiService openApiService;
    @Autowired
    private ISysMenuService menuService;

    /**
     * 查询移动应用信息
     * @return
     */
    @GetMapping("/apps")
    public ApiResult apps(){
        String sql = "SELECT * FROM dev_app WHERE show_top = 'Y' ";
        if(!openApiService.isAdmin()){
            sql +=" AND ( permission is null OR permission IN (" +
                        "SELECT perms from sys_menu m " +
                        "join sys_role_menu rm ON m.menu_id=rm.menu_id " +
                        "join sys_user_role ur ON rm.role_id=ur.role_id " +
                        "WHERE ur.user_id="+openApiService.getLoginUser().getUserId()+
                    ") )";
        }

        List<Map<String,Object>> list = dbService.query(sql);
        Map<String,Object> retMap = new HashMap<>();
        retMap.put("rows", list);
        retMap.put("total", list.size());
        return ApiResult.success(retMap);
    }

    /**
     * 刷新模块字段
     * @param moduleId
     * @return
     */
    @GetMapping("/module/reload/{moduleId}")
    public ApiResult reloadField(@PathVariable("moduleId") Long moduleId){
        TableQuery tableQuery = new TableQuery();
        tableQuery.setTable("dev_module");
        tableQuery.addData("id", moduleId);
        Map moduleData = dbService.find(tableQuery);
        if(moduleData == null || moduleData.isEmpty()){
            return ApiResult.error("模块不存在");
        }

        tableQuery = new TableQuery();
        tableQuery.setTable("dev_module_field");
        tableQuery.addData("module_id", moduleId);
        tableQuery.setPager(new SqlPager(1000,1));

        List<Map<String,Object>> fields = dbService.query(tableQuery);
        Set<String> fieldSet = new HashSet<>();
        for(Map<String,Object> f:fields){
            fieldSet.add(f.get("code").toString());
        }

        ApiModel apiModel = apiLoaderService.getModel(moduleData.get("api_model").toString());
        ApiModel fieldModel = apiLoaderService.getModel("dev_module_field");
        for(ApiField field:apiModel.getFields()){
            if(fieldSet.contains(field.getCode())){
                continue;
            }
            if(StrUtil.isNotEmpty(apiModel.getDelField()) && field.getCode().equalsIgnoreCase(apiModel.getDelField())){
                continue;
            }

            TableData fieldData = new TableData();
            fieldData.setTable("dev_module_field");
            fieldData.addData("module_id", moduleId);
            fieldData.addData("code", field.getCode());
            fieldData.addData("label", field.getName() == null ? field.getCode() : field.getName());
            fieldData.addData("type", "text");
            fieldData.addData("list", "Y");
            fieldData.addData("required", field.getNullable().equals("Y") ? "N":"Y");
            fieldData.addData("search", "0");
            fieldData.addData("mode", "0");
            fieldData.addData("sorts", 9);
            if(field.getDefaults() != null && !field.getDefaults().startsWith("@")) {
                fieldData.addData("defaults", field.getDefaults());
            }
            fieldData.setModel(fieldModel);
            dbService.insertData(fieldData, true);
        }
        return ApiResult.success();
    }

    /**
     * 复制模块字段
     * @param moduleId
     * @return
     */
    @GetMapping("/module/copy/{moduleId}")
    public ApiResult copyModule(@PathVariable("moduleId") Long moduleId){
        TableQuery tableQuery = new TableQuery();
        tableQuery.setTable("dev_module");
        tableQuery.addData("id", moduleId);
        Map moduleData = dbService.find(tableQuery);
        if(moduleData == null || moduleData.isEmpty()){
            return ApiResult.error("模块不存在");
        }

        //保存新模型
        moduleData.put("id", null);
        moduleData.put("code", moduleData.get("code").toString()+"_copy");
        moduleData.put("name", moduleData.get("name").toString()+"_复制");

        TableData tableData = new TableData();
        tableData.setTable("dev_module");
        tableData.setData(moduleData);
        dbService.insertData(tableData, false);
        Long newID = Long.parseLong(tableData.getData("id").toString());

        tableQuery = new TableQuery();
        tableQuery.setTable("dev_module_field");
        tableQuery.addData("module_id", moduleId);
        tableQuery.setPager(new SqlPager(1000,1));

        List<Map<String,Object>> fields = dbService.query(tableQuery);
        TableData fieldData = new TableData();
        fieldData.setTable("dev_module_field");
        for(Map<String,Object> f:fields){
            fieldData.setData(f);
            fieldData.addData("id", null);
            fieldData.addData("module_id", newID);
            dbService.insertData(fieldData, false);
        }

        return ApiResult.success();
    }


    /**
     * 后台模块添加到功能菜单
     * @param moduleId
     * @return
     */
    @GetMapping("/module/menu/{moduleId}")
    public ApiResult addMenu(@PathVariable("moduleId") Long moduleId){
        TableQuery tableQuery = new TableQuery();
        tableQuery.setTable("dev_module");
        tableQuery.addData("id", moduleId);
        Map moduleData = dbService.find(tableQuery);
        if(moduleData == null || moduleData.isEmpty()){
            return ApiResult.error("模块不存在");
        }

        if("check".equalsIgnoreCase(moduleData.get("type").toString())){
            addCheckMenu(moduleData);
        }else{
            addCurdMenu(moduleData);
        }

        return ApiResult.success("添加菜单成功");
    }

    private void addCheckMenu(Map moduleData){
        String moduleCode = moduleData.get("code").toString();
        //判断是否已添加
        SysMenu menu = new SysMenu();
        menu.setPath("/run/check/"+moduleCode);
        menu.setMenuName(moduleData.get("name").toString()+"审批");
        List<SysMenu> menus = menuService.selectMenuList(menu, 1L);
        if(menus != null && menus.size() > 0){
            throw new ServiceException("同名菜单已添加");
        }

        //添加新菜单
        menu.setComponent("run/check");
        menu.setMenuType("C");
        menu.setCreateTime(new Date());
        menu.setCreateBy(SecurityUtils.getUsername());
        menu.setParentId(0L);
        menu.setVisible("0");
        menu.setStatus("0");
        menu.setIsFrame("1");
        menu.setIsCache("0");
        menu.setOrderNum(9);
        menu.setPerms("run:"+moduleCode+":check");
        menu.setQuery("{\"code\":\""+ moduleCode+"\"}");
        menuService.insertMenu(menu);
    }

    private void addCurdMenu(Map moduleData){
        String moduleCode = moduleData.get("code").toString();
        //判断是否已添加
        SysMenu menu = new SysMenu();
        menu.setPath("/run/"+moduleData.get("type").toString()+"/"+moduleCode);
        menu.setMenuName(moduleData.get("name").toString());
        SysMenu old = menuService.findMenu(menu);
        if(old != null){
            throw new ServiceException("同名菜单已添加");
        }

        //添加新菜单
        menu.setComponent("run/"+moduleData.get("type").toString());
        menu.setMenuType("C");
        menu.setCreateTime(new Date());
        menu.setCreateBy(SecurityUtils.getUsername());
        menu.setParentId(0L);
        menu.setVisible("0");
        menu.setStatus("0");
        menu.setIsFrame("1");
        menu.setIsCache("0");
        menu.setOrderNum(9);
        menu.setPerms("run:"+moduleCode);
        menu.setQuery("{\"code\":\""+ moduleCode+"\"}");
        menuService.insertMenu(menu);
        String[] perms = {"add","edit", "remove", "import", "export"};
        String[] permsName = {"新增","修改", "删除", "导入", "导出"};
        for(int i=0;i<perms.length;i++){
            SysMenu pm = new SysMenu();
            pm.setParentId(menu.getMenuId());
            pm.setMenuType("F");
            pm.setMenuName(permsName[i]+moduleData.get("name").toString());
            pm.setPerms("run:"+moduleCode+":"+perms[i]);
            pm.setCreateBy(menu.getCreateBy());
            pm.setCreateTime(menu.getCreateTime());
            menuService.insertMenu(pm);
        }
    }
}
